<template>
  <div class="gesture-lock-container">
    <div class="gesture-title">手势解锁</div>
    <div class="gesture-container" ref="container">
      <canvas ref="canvas" :width="width" :height="height"></canvas>
      <div class="points-container">
        <div
            v-for="(point, index) in points"
            :key="index"
            class="point"
            :class="{ active: selectedPoints.includes(index) }"
            :style="{ left: point.x + 'px', top: point.y + 'px' }"
        >
          <div class="inner-circle" v-if="selectedPoints.includes(index)"></div>
        </div>
      </div>
    </div>

    <div class="gesture-pattern">
      <span v-if="selectedPoints.length > 0">已选择: {{ selectedPoints.length }} 个点</span>
      <span v-else>请绘制手势图案</span>
    </div>

    <button class="reset-btn" @click="resetPattern">
      <i class="reset-icon"></i>
      重置图案
    </button>
  </div>
</template>

<script setup>
import {ref, onMounted, reactive, computed} from 'vue';

// 画布尺寸
const width = 300;
const height = 300;
const canvas = ref(null);
const container = ref(null);
const ctx = ref(null);

// 九个点的位置信息
const points = reactive([]);
// 已选中的点的索引
const selectedPoints = ref([]);
// 当前触摸位置
const currentPosition = reactive({x: 0, y: 0});
// 是否正在绘制
const isDrawing = ref(false);
// 是否完成绘制
const isCompleted = ref(false);

// 初始化九个点的位置
const initPoints = () => {
  const padding = 30;
  const pointRadius = 20;
  const spacing = (width - padding * 2 - pointRadius * 2) / 2;

  for (let i = 0; i < 3; i++) {
    for (let j = 0; j < 3; j++) {
      points.push({
        x: padding + j * spacing + pointRadius,
        y: padding + i * spacing + pointRadius,
        radius: pointRadius
      });
    }
  }
};

// 检查当前触摸位置是否在某个点上
const checkPoint = (x, y) => {
  for (let i = 0; i < points.length; i++) {
    const point = points[i];
    const distance = Math.sqrt(Math.pow(x - point.x, 2) + Math.pow(y - point.y, 2));
    if (distance < point.radius && !selectedPoints.value.includes(i)) {
      selectedPoints.value.push(i);
      return true;
    }
  }
  return false;
};

// 绘制线条
const drawLine = () => {
  if (!ctx.value) return;

  ctx.value.clearRect(0, 0, width, height);

  if (selectedPoints.value.length === 0) return;

  ctx.value.beginPath();
  ctx.value.lineWidth = 3;
  ctx.value.strokeStyle = '#1989fa';

  const firstPoint = points[selectedPoints.value[0]];
  ctx.value.moveTo(firstPoint.x, firstPoint.y);

  // 绘制已选择点之间的连线
  for (let i = 1; i < selectedPoints.value.length; i++) {
    const point = points[selectedPoints.value[i]];
    ctx.value.lineTo(point.x, point.y);
  }

  // 只有在绘制中并且未完成时才绘制到当前触摸位置的连线
  if (isDrawing.value && !isCompleted.value) {
    const lastPoint = points[selectedPoints.value[selectedPoints.value.length - 1]];
    ctx.value.moveTo(lastPoint.x, lastPoint.y);
    ctx.value.lineTo(currentPosition.x, currentPosition.y);
  }

  ctx.value.stroke();
};

// 重置图案
const resetPattern = () => {
  ctx.value.clearRect(0, 0, width, height);
  selectedPoints.value = [];
  isCompleted.value = false;
};

// 触摸开始
const handleTouchStart = (e) => {
  if (isCompleted.value) return;

  e.preventDefault();
  resetPattern();

  const touch = e.touches[0];
  const rect = container.value.getBoundingClientRect();
  const x = touch.clientX - rect.left;
  const y = touch.clientY - rect.top;

  currentPosition.x = x;
  currentPosition.y = y;

  checkPoint(x, y);
  isDrawing.value = true;
  drawLine();
};

// 触摸移动
const handleTouchMove = (e) => {
  if (!isDrawing.value || isCompleted.value) return;

  e.preventDefault();

  const touch = e.touches[0];
  const rect = container.value.getBoundingClientRect();
  const x = touch.clientX - rect.left;
  const y = touch.clientY - rect.top;

  currentPosition.x = x;
  currentPosition.y = y;

  checkPoint(x, y);
  drawLine();
};

// 触摸结束
const handleTouchEnd = () => {
  if (!isDrawing.value) return;

  isDrawing.value = false;
  isCompleted.value = true;

  // 验证手势密码
  if (selectedPoints.value.length > 0) {
    console.log('手势密码:', selectedPoints.value.join(''));
    // 更新最后一次绘制，去掉连接到鼠标的线段
    drawLine();
  }
};

onMounted(() => {
  ctx.value = canvas.value.getContext('2d');
  initPoints();

  // 添加触摸事件监听
  container.value.addEventListener('touchstart', handleTouchStart);
  container.value.addEventListener('touchmove', handleTouchMove);
  container.value.addEventListener('touchend', handleTouchEnd);

  // 鼠标事件（为了在桌面浏览器中测试）
  container.value.addEventListener('mousedown', (e) => {
    if (isCompleted.value) return;

    resetPattern();

    const rect = container.value.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;

    currentPosition.x = x;
    currentPosition.y = y;

    checkPoint(x, y);
    isDrawing.value = true;
    drawLine();
  });

  container.value.addEventListener('mousemove', (e) => {
    if (!isDrawing.value || isCompleted.value) return;

    const rect = container.value.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;

    currentPosition.x = x;
    currentPosition.y = y;

    checkPoint(x, y);
    drawLine();
  });

  container.value.addEventListener('mouseup', handleTouchEnd);
});
</script>

<style scoped>
.gesture-lock-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: 350px;
  margin: 0 auto;
  padding: 20px;
  background-color: #f7f9fc;
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}

.gesture-title {
  font-size: 20px;
  font-weight: 600;
  color: #333;
  margin-bottom: 20px;
}

.gesture-container {
  position: relative;
  width: 300px;
  height: 300px;
  margin: 0 auto;
  touch-action: none;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

canvas {
  position: absolute;
  z-index: 1;
  border-radius: 8px;
}

.points-container {
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: 0;
}

.point {
  position: absolute;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: #ffffff;
  border: 2px solid #e0e0e0;
  transform: translate(-50%, -50%);
  box-sizing: border-box;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: all 0.2s ease;
}

.point.active {
  border-color: #1989fa;
  background-color: rgba(25, 137, 250, 0.1);
}

.inner-circle {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background-color: #1989fa;
}

.gesture-pattern {
  margin-top: 20px;
  font-size: 14px;
  color: #666;
  height: 20px;
}

.reset-btn {
  margin-top: 20px;
  padding: 8px 16px;
  background-color: #1989fa;
  color: white;
  border: none;
  border-radius: 4px;
  font-size: 14px;
  cursor: pointer;
  display: flex;
  align-items: center;
  transition: background-color 0.2s;
}

.reset-btn:hover {
  background-color: #0b76e0;
}

.reset-icon {
  display: inline-block;
  width: 16px;
  height: 16px;
  margin-right: 6px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 9h7V2l-2.35 4.35z'/%3E%3C/svg%3E");
  background-size: contain;
  background-repeat: no-repeat;
}
</style>